package com.itedge.solutionmanager.domain.impl;

import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.Size;
import java.util.Date;
import java.util.Set;
import java.util.HashSet;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.Column;
import javax.persistence.EnumType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.CascadeType;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.JoinColumn;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;

import com.itedge.infrastructure.domain.IEntity;
import com.itedge.infrastructure.domain.IProcessEntity;
import com.itedge.solutionmanager.enumeration.SolutionPhase;

/**
 * Solution domain object, holding state of solution, all relations to other objects
 * and providing some bussines method to interact with.
 * 
 * @author jhe
 *
 */
@Entity
@Table(name="SOLUTION")
public class Solution implements IEntity, IProcessEntity {
    
    @Size(max = 4000)
    @Column(name="DESCRIPTION")
    private String description;
    
    @Size(max = 4000)
    @Column(name="INITIAL_INFO")
    private String initialInfo;
    
    @Column(name="NAME")
    @Size(max = 255)
    private String name;

    @Enumerated(EnumType.ORDINAL)
    @Column(name="PHASE")
    private SolutionPhase phase;

    @Column(name="PROCESS_ID")
    private String processInstanceId;    

	@OneToMany(cascade = CascadeType.ALL)
    @JoinTable(name="SOLUTION_DOCUMENTS",
            joinColumns=@JoinColumn(name="SOLUTION_ID"),
            inverseJoinColumns=@JoinColumn(name="DOCUMENT_ID")
        )
    private Set<Document> relatedDocuments = new HashSet<Document>();    

	@ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name="SOLUTIONS_EMPLOYEES",
            joinColumns=@JoinColumn(name="SOLUTION_ID"),
            inverseJoinColumns=@JoinColumn(name="EMPLOYEE_ID")
        )
    private Set<Employee> assignedEmployees = new HashSet<Employee>();    

    @ManyToOne
    private Customer customer;    
    
	@Column(name="DELIVERY_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "S-")
    private Date deliveryDate;
	
	@Column(name="DEVELOPMENT_START_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "S-")
    private Date developmentStartDate;
	
	@Column(name="CONTACT_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "S-")
    private Date contactDate;

	@Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

	@Version
    @Column(name = "version")
    private Integer version;

    public Set<Document> getRelatedDocuments() {
		return relatedDocuments;
	}

	public void setRelatedDocuments(Set<Document> relatedDocuments) {
		this.relatedDocuments = relatedDocuments;
	}	
	
	public String getInitialInfo() {
		return initialInfo;
	}

	public void setInitialInfo(String initialInfo) {
		this.initialInfo = initialInfo;
	}

	public Date getDeliveryDate() {
		return deliveryDate;
	}

	public void setDeliveryDate(Date deliveryDate) {
		this.deliveryDate = deliveryDate;
	}

	public Date getDevelopmentStartDate() {
		return developmentStartDate;
	}

	public void setDevelopmentStartDate(Date developmentStartDate) {
		this.developmentStartDate = developmentStartDate;
	}

	public Date getContactDate() {
		return contactDate;
	}

	public void setContactDate(Date contactDate) {
		this.contactDate = contactDate;
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}	
	
	@Override
	public String getProcessInstanceId() {
		return this.processInstanceId;
	}
	
	@Override
	public void setProcessInstanceId(String id) {
		this.processInstanceId = id;
	}
	
	@Override
	public Long getId() {
        return this.id;
    }

	public void setId(Long id) {
        this.id = id;
    }

	@Override
	public Integer getVersion() {
        return this.version;
    }

	public void setVersion(Integer version) {
        this.version = version;
    }

	public String getDescription() {
        return this.description;
    }

	public void setDescription(String description) {
        this.description = description;
    }

	public String getName() {
        return this.name;
    }

	public void setName(String name) {
        this.name = name;
    }

	public SolutionPhase getPhase() {
        return this.phase;
    }

	public void setPhase(SolutionPhase phase) {
        this.phase = phase;
    }

	public Set<Employee> getAssignedEmployees() {
        return this.assignedEmployees;
    }

	public void setAssignedEmployees(Set<Employee> employees) {
        this.assignedEmployees = employees;
    }
	
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(this.name != null ? this.name +" (initInfo: " : "initInfo: ");		
		sb.append(this.initialInfo);
		sb.append(this.name != null ? ")" : "");
		return sb.toString();		
	}
}
